package com.sd365.gateway.authentication.service.impl;

import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSONObject;
import com.sd365.common.util.TokenUtil;
import com.sd365.gateway.authentication.service.AuthenticationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
/**
 * @Class AuthenticationServiceImpl
 * @Description abel.zhan 2022-10-12 重构认证代码
 *  需要实现  AuthenticationService  按系统开发指引流程实现认证逻辑
 * @Author Administrator
 * @Date 2022-10-12  20:08
 * @version 1.0.0
 */
@Slf4j
@Service
public class AuthenticationServiceImpl  implements AuthenticationService{
    /**
     * 定义了认证接口的URL
     */
    public static final   String AUTH_URL = "http://sd365-permission-center/permission/centre/v1/user/auth?code=%s&account=%s&password=%s";
    /**
     * RedisTemplateConfig 中生成
     */
    @Resource(name = "tokenRedisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * CurrentServiceTemplateBeanConfig.java中定义
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 默认设置三天过期 单位毫秒 1000 * 60 * 60 * 24 * 3 = 86400
     */
    @Value("${jwt.period}")
    private Long period = 259200000L;
    /**
     * 一天
     */
    private static final Long ONE_DAY = 86400000L;
    private static final String USER_TOKEN_KEY = "user:token:";

    @Override
    public String getToken(String code, String account, String password) {
        HttpServletRequest request =((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();

        LinkedHashMap authResult = null;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set(HttpHeaders.USER_AGENT, request.getHeader("USER-AGENT"));

            HttpEntity httpEntity = new HttpEntity<>(null, headers);

            authResult = restTemplate.exchange(String.format(AUTH_URL, code, account, password), HttpMethod.GET, httpEntity, LinkedHashMap.class).getBody();
            return createJWTtoken(code, account, authResult);
        }catch (Exception e) {
            log.info("Authentication error", e);
            throw e;
        }
    }private String createJWTtoken(String code, String account, LinkedHashMap authResult) {
        final LinkedHashMap body =  (LinkedHashMap)authResult.get("body");
        Integer UserVoCode = (Integer) (body).get("code");
        if (UserVoCode != HttpStatus.HTTP_OK){
            return new JSONObject(authResult).toJSONString();
        }
        ArrayList roleIds = (ArrayList) (body).get("roleIds");
        Long userId = Long.parseLong((String) body.getOrDefault("id",-1));
        Long tenantId = Long.parseLong((String) body.getOrDefault("tenantId",-1));
        Long companyId = Long.parseLong((String) body.getOrDefault("companyId",-1));
        Long orgId = Long.parseLong((String) body.getOrDefault("orgId",-1));
        String username = (String) body.getOrDefault("name","-1");
        final JSONObject header = new JSONObject();
        final JSONObject playLoad = new JSONObject();
        header.put("alg","HS256");
        header.put("typ","JWT");

        playLoad.put("account",account);
        playLoad.put("roleIds",roleIds);
        playLoad.put("tenantId",tenantId);
        playLoad.put("companyId",companyId);
        playLoad.put("orgId",orgId);
        playLoad.put("userId",userId);
        playLoad.put("username",username);
        playLoad.put("code",code);
        playLoad.put("expiresAt",new Date(System.currentTimeMillis()+period));
        String jwtProtocol = header.toJSONString() + "." + playLoad.toJSONString();
        ((LinkedHashMap) (body).get("data")).put("token",TokenUtil.encoderToken(jwtProtocol));
        redisTemplate.opsForValue().set(userId.toString(),"userId:"+ userId.toString(),1L,TimeUnit.DAYS);
        String encoderToken = TokenUtil.encoderToken(jwtProtocol);
        stringRedisTemplate.opsForValue().set(USER_TOKEN_KEY+userId,encoderToken,period+ONE_DAY,TimeUnit.MILLISECONDS);
        return new JSONObject(authResult).toJSONString();
    }
}
